From 7fdfb8644169a25805afd32f00ced38c1c14cec8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Havl=C3=AD=C4=8Dek?= <80639037+havel06@users.noreply.github.com> Date: Wed, 25 Jan 2023 21:46:34 +0100 Subject: Allow certain blocks to be placed on top of upside-down stairs/slabs (#5468) * Placing certain blocks on top of upside down slabs and stairs * remove TODO * fix style errors * IsAnyStairType helper function * Block placement on stairs and slabs --- src/BlockInfo.h | 1 - src/Blocks/BlockButton.h | 37 +++++++++++++++++++++++++- src/Blocks/BlockComparator.h | 17 +++++++----- src/Blocks/BlockLever.h | 26 +++++++++++++++++- src/Blocks/BlockPressurePlate.h | 20 ++++++++++++-- src/Blocks/BlockRail.h | 30 +++++++++++++++++++-- src/Blocks/BlockRedstoneRepeater.h | 19 +++++++++----- src/Blocks/BlockRedstoneWire.h | 20 +++++++++----- src/Blocks/BlockStairs.h | 29 +++++++++++++++++--- src/Blocks/BlockTorch.h | 54 ++++++++++++++++++++++---------------- 10 files changed, 202 insertions(+), 51 deletions(-) diff --git a/src/BlockInfo.h b/src/BlockInfo.h index a15868abe..7d2781847 100644 --- a/src/BlockInfo.h +++ b/src/BlockInfo.h @@ -65,7 +65,6 @@ public: - bool IsBlockWater(BLOCKTYPE a_BlockType); bool IsBlockIce(BLOCKTYPE a_BlockType); diff --git a/src/Blocks/BlockButton.h b/src/Blocks/BlockButton.h index d703d73bd..1a141eff3 100644 --- a/src/Blocks/BlockButton.h +++ b/src/Blocks/BlockButton.h @@ -1,10 +1,15 @@ #pragma once #include "BlockHandler.h" +#include "BlockSlab.h" +#include "BlockStairs.h" #include "../BlockInfo.h" #include "../Chunk.h" +#include "Defines.h" +#include "Entities/Player.h" #include "Mixins.h" #include "ChunkInterface.h" +#include "World.h" @@ -132,7 +137,37 @@ private: return false; } BLOCKTYPE SupportBlockType; - a_Chunk.UnboundedRelGetBlockType(SupportRelPos, SupportBlockType); + NIBBLETYPE SupportBlockMeta; + a_Chunk.UnboundedRelGetBlock(SupportRelPos, SupportBlockType, SupportBlockMeta); + eBlockFace Face = BlockMetaDataToBlockFace(a_Meta); + + // upside down slabs + if (cBlockSlabHandler::IsAnySlabType(SupportBlockType)) + { + return (Face == BLOCK_FACE_YP) && (SupportBlockMeta & E_META_WOODEN_SLAB_UPSIDE_DOWN); + } + + // stairs (top and sides) + if (cBlockStairsHandler::IsAnyStairType(SupportBlockType)) + { + switch (Face) + { + case eBlockFace::BLOCK_FACE_YP: + return (SupportBlockMeta & E_BLOCK_STAIRS_UPSIDE_DOWN); + case eBlockFace::BLOCK_FACE_XP: + return ((SupportBlockMeta & 0b11) == E_BLOCK_STAIRS_XP); + case eBlockFace::BLOCK_FACE_XM: + return ((SupportBlockMeta & 0b11) == E_BLOCK_STAIRS_XM); + case eBlockFace::BLOCK_FACE_ZP: + return ((SupportBlockMeta & 0b11) == E_BLOCK_STAIRS_ZP); + case eBlockFace::BLOCK_FACE_ZM: + return ((SupportBlockMeta & 0b11) == E_BLOCK_STAIRS_ZM); + default: + { + return false; + } + } + } return cBlockInfo::FullyOccupiesVoxel(SupportBlockType); } diff --git a/src/Blocks/BlockComparator.h b/src/Blocks/BlockComparator.h index e58b386c3..18aa2a8b9 100644 --- a/src/Blocks/BlockComparator.h +++ b/src/Blocks/BlockComparator.h @@ -167,14 +167,19 @@ private: { return true; } - else if (cBlockSlabHandler::IsAnySlabType(BelowBlock)) + + // upside down slabs + if (cBlockSlabHandler::IsAnySlabType(BelowBlock)) { - // Check if the slab is turned up side down - if ((BelowBlockMeta & 0x08) == 0x08) - { - return true; - } + return BelowBlockMeta & E_META_WOODEN_SLAB_UPSIDE_DOWN; } + + // upside down stairs + if (cBlockStairsHandler::IsAnyStairType(BelowBlock)) + { + return BelowBlockMeta & E_BLOCK_STAIRS_UPSIDE_DOWN; + } + return false; } diff --git a/src/Blocks/BlockLever.h b/src/Blocks/BlockLever.h index bf6f911a1..60db4ddee 100644 --- a/src/Blocks/BlockLever.h +++ b/src/Blocks/BlockLever.h @@ -2,6 +2,9 @@ #include "BlockHandler.h" #include "../Chunk.h" +#include "Blocks/BlockStairs.h" +#include "ChunkDef.h" +#include "Defines.h" #include "Mixins.h" #include "BlockSlab.h" @@ -117,7 +120,28 @@ private: (((NeighborMeta & 0x08) == 0) && (NeighborFace == BLOCK_FACE_BOTTOM)) ); } - + else if (cBlockStairsHandler::IsAnyStairType(NeighborBlockType)) + { + switch (NeighborFace) + { + case eBlockFace::BLOCK_FACE_YM: + return !(NeighborMeta & E_BLOCK_STAIRS_UPSIDE_DOWN); + case eBlockFace::BLOCK_FACE_YP: + return (NeighborMeta & E_BLOCK_STAIRS_UPSIDE_DOWN); + case eBlockFace::BLOCK_FACE_XP: + return ((NeighborMeta & 0b11) == E_BLOCK_STAIRS_XP); + case eBlockFace::BLOCK_FACE_XM: + return ((NeighborMeta & 0b11) == E_BLOCK_STAIRS_XM); + case eBlockFace::BLOCK_FACE_ZP: + return ((NeighborMeta & 0b11) == E_BLOCK_STAIRS_ZP); + case eBlockFace::BLOCK_FACE_ZM: + return ((NeighborMeta & 0b11) == E_BLOCK_STAIRS_ZM); + default: + { + return false; + } + } + } return false; } diff --git a/src/Blocks/BlockPressurePlate.h b/src/Blocks/BlockPressurePlate.h index d2f05b2e7..6d852bfc0 100644 --- a/src/Blocks/BlockPressurePlate.h +++ b/src/Blocks/BlockPressurePlate.h @@ -2,6 +2,9 @@ #pragma once #include "BlockHandler.h" +#include "BlockSlab.h" +#include "../Chunk.h" +#include "BlockStairs.h" @@ -24,9 +27,22 @@ private: return false; } - // TODO: check if the block is upside-down slab or upside-down stairs + BLOCKTYPE Block; + NIBBLETYPE BlockMeta; + a_Chunk.GetBlockTypeMeta(a_Position.addedY(-1), Block, BlockMeta); + + // upside down slabs + if (cBlockSlabHandler::IsAnySlabType(Block)) + { + return BlockMeta & E_META_WOODEN_SLAB_UPSIDE_DOWN; + } + + // upside down stairs + if (cBlockStairsHandler::IsAnyStairType(Block)) + { + return BlockMeta & E_BLOCK_STAIRS_UPSIDE_DOWN; + } - const auto Block = a_Chunk.GetBlock(a_Position.addedY(-1)); switch (Block) { case E_BLOCK_ACACIA_FENCE: diff --git a/src/Blocks/BlockRail.h b/src/Blocks/BlockRail.h index 6c4367334..4e2e6211f 100644 --- a/src/Blocks/BlockRail.h +++ b/src/Blocks/BlockRail.h @@ -1,6 +1,14 @@ - #pragma once +#include "BlockHandler.h" +#include "BlockSlab.h" +#include "BlockStairs.h" +#include "BlockType.h" +#include "Blocks/Mixins.h" +#include "../BlockInfo.h" +#include "../Chunk.h" +#include "ChunkDef.h" + @@ -154,9 +162,26 @@ public: private: + static bool CanBeSupportedBy(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) + { + if (cBlockSlabHandler::IsAnySlabType(a_BlockType)) + { + return (a_BlockMeta & E_META_WOODEN_SLAB_UPSIDE_DOWN); + } + else if (cBlockStairsHandler::IsAnyStairType(a_BlockType)) + { + return (a_BlockMeta & E_BLOCK_STAIRS_UPSIDE_DOWN); + } + return cBlockInfo::FullyOccupiesVoxel(a_BlockType); + } + virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, NIBBLETYPE a_Meta) const override { - if ((a_Position.y <= 0) || !cBlockInfo::FullyOccupiesVoxel(a_Chunk.GetBlock(a_Position.addedY(-1)))) + BLOCKTYPE BelowBlock; + NIBBLETYPE BelowBlockMeta; + a_Chunk.GetBlockTypeMeta(a_Position.addedY(-1), BelowBlock, BelowBlockMeta); + + if ((a_Position.y <= 0) || !CanBeSupportedBy(BelowBlock, BelowBlockMeta)) { return false; } @@ -187,6 +212,7 @@ private: return cBlockInfo::FullyOccupiesVoxel(BlockType); } } + return true; } diff --git a/src/Blocks/BlockRedstoneRepeater.h b/src/Blocks/BlockRedstoneRepeater.h index 4b9650e90..893691d7b 100644 --- a/src/Blocks/BlockRedstoneRepeater.h +++ b/src/Blocks/BlockRedstoneRepeater.h @@ -2,9 +2,11 @@ #pragma once #include "BlockHandler.h" +#include "BlockType.h" #include "Mixins.h" #include "ChunkInterface.h" #include "BlockSlab.h" +#include "BlockStairs.h" #include "../Chunk.h" @@ -120,14 +122,19 @@ private: { return true; } - else if (cBlockSlabHandler::IsAnySlabType(BelowBlock)) + + // upside down slabs + if (cBlockSlabHandler::IsAnySlabType(BelowBlock)) { - // Check if the slab is turned up side down - if ((BelowBlockMeta & 0x08) == 0x08) - { - return true; - } + return BelowBlockMeta & E_META_WOODEN_SLAB_UPSIDE_DOWN; } + + // upside down stairs + if (cBlockStairsHandler::IsAnyStairType(BelowBlock)) + { + return BelowBlockMeta & E_BLOCK_STAIRS_UPSIDE_DOWN; + } + return false; } diff --git a/src/Blocks/BlockRedstoneWire.h b/src/Blocks/BlockRedstoneWire.h index 3976afa90..de8e59a40 100644 --- a/src/Blocks/BlockRedstoneWire.h +++ b/src/Blocks/BlockRedstoneWire.h @@ -3,7 +3,8 @@ #include "BlockHandler.h" #include "BlockSlab.h" - +#include "BlockStairs.h" +#include "../Chunk.h" @@ -34,14 +35,19 @@ private: { return true; } - else if (cBlockSlabHandler::IsAnySlabType(BelowBlock)) + + // upside down slabs + if (cBlockSlabHandler::IsAnySlabType(BelowBlock)) + { + return BelowBlockMeta & E_META_WOODEN_SLAB_UPSIDE_DOWN; + } + + // upside down stairs + if (cBlockStairsHandler::IsAnyStairType(BelowBlock)) { - // Check if the slab is turned up side down - if ((BelowBlockMeta & 0x08) == 0x08) - { - return true; - } + return BelowBlockMeta & E_BLOCK_STAIRS_UPSIDE_DOWN; } + return false; } diff --git a/src/Blocks/BlockStairs.h b/src/Blocks/BlockStairs.h index 55a9e877e..76614bb62 100644 --- a/src/Blocks/BlockStairs.h +++ b/src/Blocks/BlockStairs.h @@ -16,6 +16,32 @@ public: using Super::Super; + static bool IsAnyStairType(BLOCKTYPE a_Block) + { + switch (a_Block) + { + case E_BLOCK_SANDSTONE_STAIRS: + case E_BLOCK_BIRCH_WOOD_STAIRS: + case E_BLOCK_QUARTZ_STAIRS: + case E_BLOCK_JUNGLE_WOOD_STAIRS: + case E_BLOCK_RED_SANDSTONE_STAIRS: + case E_BLOCK_COBBLESTONE_STAIRS: + case E_BLOCK_STONE_BRICK_STAIRS: + case E_BLOCK_OAK_WOOD_STAIRS: + case E_BLOCK_ACACIA_WOOD_STAIRS: + case E_BLOCK_PURPUR_STAIRS: + case E_BLOCK_DARK_OAK_WOOD_STAIRS: + case E_BLOCK_BRICK_STAIRS: + case E_BLOCK_NETHER_BRICK_STAIRS: + case E_BLOCK_SPRUCE_WOOD_STAIRS: + return true; + default: + { + return false; + } + } + } + private: virtual NIBBLETYPE MetaMirrorXZ(NIBBLETYPE a_Meta) const override @@ -25,9 +51,6 @@ private: } - - - virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override { UNUSED(a_Meta); diff --git a/src/Blocks/BlockTorch.h b/src/Blocks/BlockTorch.h index 0b96ad246..ad69cf5eb 100644 --- a/src/Blocks/BlockTorch.h +++ b/src/Blocks/BlockTorch.h @@ -1,8 +1,12 @@ #pragma once #include "BlockHandler.h" +#include "BlockSlab.h" +#include "BlockStairs.h" #include "../Chunk.h" +#include "BlockType.h" #include "ChunkInterface.h" +#include "Defines.h" #include "Mixins.h" @@ -22,6 +26,34 @@ public: /** Returns true if the torch can be placed on the specified block's face. */ static bool CanBePlacedOn(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, eBlockFace a_BlockFace) { + // upside down slabs + if (cBlockSlabHandler::IsAnySlabType(a_BlockType)) + { + return (a_BlockFace == BLOCK_FACE_YP) && (a_BlockMeta & E_META_WOODEN_SLAB_UPSIDE_DOWN); + } + + // stairs (top and sides) + if (cBlockStairsHandler::IsAnyStairType(a_BlockType)) + { + switch (a_BlockFace) + { + case eBlockFace::BLOCK_FACE_YP: + return (a_BlockMeta & E_BLOCK_STAIRS_UPSIDE_DOWN); + case eBlockFace::BLOCK_FACE_XP: + return ((a_BlockMeta & 0b11) == E_BLOCK_STAIRS_XP); + case eBlockFace::BLOCK_FACE_XM: + return ((a_BlockMeta & 0b11) == E_BLOCK_STAIRS_XM); + case eBlockFace::BLOCK_FACE_ZP: + return ((a_BlockMeta & 0b11) == E_BLOCK_STAIRS_ZP); + case eBlockFace::BLOCK_FACE_ZM: + return ((a_BlockMeta & 0b11) == E_BLOCK_STAIRS_ZM); + default: + { + return false; + } + } + } + switch (a_BlockType) { case E_BLOCK_END_PORTAL_FRAME: @@ -44,28 +76,6 @@ public: // Torches can only be placed on top of these blocks return (a_BlockFace == BLOCK_FACE_YP); } - case E_BLOCK_STONE_SLAB: - case E_BLOCK_WOODEN_SLAB: - { - // Toches can be placed only on the top of top-half-slabs - return ((a_BlockFace == BLOCK_FACE_YP) && ((a_BlockMeta & 0x08) == 0x08)); - } - case E_BLOCK_OAK_WOOD_STAIRS: - case E_BLOCK_COBBLESTONE_STAIRS: - case E_BLOCK_BRICK_STAIRS: - case E_BLOCK_STONE_BRICK_STAIRS: - case E_BLOCK_NETHER_BRICK_STAIRS: - case E_BLOCK_SANDSTONE_STAIRS: - case E_BLOCK_SPRUCE_WOOD_STAIRS: - case E_BLOCK_BIRCH_WOOD_STAIRS: - case E_BLOCK_JUNGLE_WOOD_STAIRS: - case E_BLOCK_QUARTZ_STAIRS: - case E_BLOCK_ACACIA_WOOD_STAIRS: - case E_BLOCK_DARK_OAK_WOOD_STAIRS: - case E_BLOCK_RED_SANDSTONE_STAIRS: - { - return (a_BlockFace == BLOCK_FACE_TOP) && (a_BlockMeta & E_BLOCK_STAIRS_UPSIDE_DOWN); - } default: { if (cBlockInfo::FullyOccupiesVoxel(a_BlockType)) -- cgit v1.2.3